#include "ui.h"
#include "thread.h"
#include "options.h"
#include "resource.h"

#include <windowsx.h>

static HINSTANCE hInstance;
static LPSTR     pCmdLine;
static int       nCmdShow;
static HWND      hWnd;

LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM);

void init_ui(HINSTANCE _hInstance, LPSTR _pCmdLine, int _nCmdShow)
{
    hInstance = _hInstance;
    pCmdLine = _pCmdLine;
    nCmdShow = _nCmdShow;
}

void create_mutex(void)
{
    HANDLE m_hMutex = CreateMutex(NULL, false, MUTEX_GLOBAL);
    if (GetLastError() == ERROR_ALREADY_EXISTS) {
        MessageBox(NULL, MSG_ERROR_DUPLICATED, MSG_ERROR_CAPTION, MB_OK);
        CloseHandle(m_hMutex);
        m_hMutex = NULL;
        exit(EXIT_FAILURE);
    }
}

void create_wclass(void)
{
    WNDCLASSEX wcex;

    wcex.cbSize = sizeof(WNDCLASSEX); 
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = (WNDPROC)WindowProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = hInstance;
    wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON));
    wcex.hIconSm = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON));
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground = NULL;
    wcex.lpszMenuName = NULL;
    wcex.lpszClassName = CLASS_NAME;

    assert(wcex.hIcon != NULL);
    RegisterClassEx(&wcex);
}

void create_main_window(void)
{
    hWnd = CreateWindowEx(
            WS_EX_LAYERED | WS_EX_TOPMOST | WS_EX_TOOLWINDOW,
            CLASS_NAME,
            WINDOW_NAME,
            0,
            10, 10, UI_WIDTH, UI_HEIGHT,
            NULL,       // Parent window    
            NULL,       // Menu
            hInstance,  // Instance handle
            NULL        // Additional application data
    );
    assert(hWnd != NULL);
    SetLayeredWindowAttributes(hWnd, 0, (BYTE)ui_alpha, LWA_ALPHA);
    ShowWindow(hWnd, SW_SHOW);
    UpdateWindow(hWnd);
}

void terminate(void)
{
    DestroyWindow(hWnd);
    PostQuitMessage(0);
    HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, false, GetCurrentProcessId());
    TerminateProcess(hProcess, 0);
    // ExitProcess(0);
    // ShellExecute(NULL, L"Open", L"tskill aippt", NULL, NULL, SW_SHOWNORMAL);
    exit(0);
}

void display_context_menu(int x, int y)
{
    HMENU hmenu;            // top-level menu 
    HMENU hmenuTrackPopup;  // shortcut menu 
 
    // Load the menu resource. 
 
    hmenu = LoadMenu(hInstance, MAKEINTRESOURCE(IDM_CONTEXT));
    assert(hmenu != NULL);

    hmenuTrackPopup = GetSubMenu(hmenu, 0); 
    assert(hmenuTrackPopup != NULL);
 
    TrackPopupMenu(hmenuTrackPopup, 
                   TPM_LEFTALIGN | TPM_RIGHTBUTTON, 
                   x, y, 0, hWnd, NULL); 

    DestroyMenu(hmenu); 
}

    
void paint(HWND hwnd, bool update_only)
{
    static result_t ret;
    static int stt = 0;
    static char flag_exp = 'o';

    static char show_flag = 'o';
    static clock_t show_end = -10000;

    if (update_only)
    {   
        get_result(&ret);
        int st = (int) (ret.status * 255);
        if (st < 0 || st > 255) st = 0;
        
        if (st > stt)
        {
            stt = st;
            flag_exp = ret.flag_next;
        }
        if (ret.flag_ui)
        {
            show_end = clock() + UI_SHOW_TEXT_TIME;
            show_flag = ret.flag_ui;
            ret.flag_ui = '\0';
            set_result(&ret);
        }
        return;
    }

    stt = (int) (stt * 0.90);

    HDC hdc = GetDC(hwnd);
    RECT rc;
    GetClientRect(hwnd, &rc);

    static wchar_t xx[10];
    
    if (clock() < show_end)
    {
        if (show_flag == '<')
            wcscpy(xx, UI_TEXT_LEFT);
        if (show_flag == '>')
            wcscpy(xx, UI_TEXT_RIGHT);
        if (show_flag == '-')
            wcscpy(xx, UI_TEXT_LEFT2);
        if (show_flag == '+')
            wcscpy(xx, UI_TEXT_RIGHT2);
        if (show_flag == ',')
            wcscpy(xx, UI_TEXT_CLAP);
        if (show_flag == '.')
            wcscpy(xx, UI_TEXT_CLAP2);
        if (show_flag == 'a')
            wcscpy(xx, UI_TEXT_DONG);
        if (show_flag == 'b')
            wcscpy(xx, UI_TEXT_KA);
        if (show_flag == 'c')
            wcscpy(xx, UI_TEXT_RENDA);
    } else
    {
        if (ret.flag == 'o')
            wcscpy(xx, UI_TEXT_NORMAL);
        if (ret.flag == ',')
            wcscpy(xx, UI_TEXT_WAIT2);
        if (ret.flag == 'm')
            wcscpy(xx, UI_TEXT_DRAG);
    }
    
    int melt = 255 - (int)(255. * (clock() - ret.begin) / CLOCKS_PER_SEC);
    if (melt > 255) melt = 255;
    if (melt < 0) melt = 0;
    melt = melt / 4 + 255 - 64;
    COLORREF clr;
    if (ret.flag == 'o')
        clr = RGB(0,255,0);
    if ((ret.flag == 'o' &&
            (flag_exp == '>' || flag_exp == '<')) || ret.flag == '\0')
        clr = RGB(stt, 255 - stt, 0);
    if (ret.flag == 'o' && flag_exp == 'a')
            clr = RGB(stt, 255 - stt, 0);
    if (ret.flag == 'o' && flag_exp == 'b')
            clr = RGB(0, 255 - stt, stt);
    if (ret.flag == 'o' && flag_exp == 'c')
            clr = RGB(stt, 255 - stt, stt);
    if (ret.flag == 'o' && flag_exp == ',')
        clr = RGB(0, 255 - stt, stt);
    if (ret.flag == ',' && (flag_exp == '+' || flag_exp == '-'))
        clr = RGB(stt, 0, melt);
    if (ret.flag == ',' && flag_exp == '.')
        clr = RGB(0, stt, melt);
    if (ret.flag == 'm')
        clr = RGB(0, 255, melt);
    HBRUSH hbr = CreateSolidBrush(clr);
    FillRect(hdc, &rc, hbr);
    DeleteObject(hbr);

    
    SetTextColor(hdc, RGB(0,0,0));
    TextOut(hdc, TEXT_OFFSET_X, TEXT_OFFSET_Y, xx, wcslen(xx));

    ReleaseDC(hwnd, hdc);
    ValidateRect(hwnd, &rc);
}
    
    LRESULT CALLBACK
WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg) {
    case WM_CREATE:
        SetTimer(hwnd, UI_TIMER_ID, UI_DELAY, NULL);
        break;

    case WM_QUIT:
    case WM_DESTROY:
        terminate();
        break;

    case WM_CONTEXTMENU:
        display_context_menu(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
        break;

    case WM_COMMAND:
        switch (LOWORD(wParam)) {
        case IDM_EXIT:
            terminate();
            break;
        case IDM_HELP:
            ShellExecute(hwnd, L"Open", L"tutor.txt", NULL, NULL, SW_SHOWNORMAL);
            break;
        case IDM_CALIBRATION:
            logf("Hello world\n");
            show_video = 1;
            break;
        }
        break;

    case WM_TIMER:
        InvalidateRect(hwnd, NULL, true);
    case WM_PAINT:
        paint(hwnd, false);

    default:
        return DefWindowProc(hwnd, uMsg, wParam, lParam);
        break;
    }

    return EXIT_SUCCESS;
}
